package com.qujia.station.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qujia.common.constant.UserConstants;
import com.qujia.common.core.domain.AjaxResult;
import com.qujia.common.core.domain.entity.SysUser;
import com.qujia.common.exception.BaseException;
import com.qujia.common.utils.SecurityUtils;
import com.qujia.station.domain.*;
import com.qujia.station.domain.dto.OutboundRecordsDetailsDto;
import com.qujia.station.domain.dto.OutboundRecordsDto;
import com.qujia.station.domain.dto.OutboundRecordsQueryDto;
import com.qujia.station.domain.vo.OutboundRecordsVo;
import com.qujia.station.enums.StorageStatusEnum;
import com.qujia.station.mapper.OutboundRecordsMapper;
import com.qujia.station.mapper.StationMapper;
import com.qujia.station.service.*;
import com.qujia.station.utils.CodeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

@Service
@Slf4j
public class OutboundRecordsServiceImpl extends ServiceImpl<OutboundRecordsMapper, OutboundRecords> implements OutboundRecordsService {

    @Autowired
    private StorageRecordsService storageRecordsService;
    @Autowired
    private StorageRecordsDetailsService storageRecordsDetailsService;
    @Autowired
    private OutboundRecordsDetailsService outboundRecordsDetailsService;
    @Autowired
    private CommodityService commodityService;
    @Resource
    private StationMapper stationMapper;

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public AjaxResult addOutboundOrder(OutboundRecordsDto outboundRecordsDto) {
        log.info("新增调拨出库入参：{}", JSONObject.toJSONString(outboundRecordsDto));
        SysUser user = SecurityUtils.getLoginUser().getUser();
        if(null==user){
            throw new BaseException("当前用户不存在");
        }
        List<OutboundRecordsDetailsDto> outboundRecordsDetailsDtos = outboundRecordsDto.getOutboundRecordsDetailsDtos();
        if(CollectionUtil.isEmpty(outboundRecordsDetailsDtos)){
            throw new BaseException("没有选择商品进行调拨");
        }
        Station outboundStation = stationMapper.selectStationById(outboundRecordsDto.getOutboundStationId());
        Station storageStation = stationMapper.selectStationById(outboundRecordsDto.getStorageStationId());
        //出库单生成的单据编码
        String code = CodeUtil.createCode();
        log.info("出库单生成的单据编码:{}",code);
        //计算调拨商品总数
        Long sum = outboundRecordsDetailsDtos.stream().map(OutboundRecordsDetailsDto::getInventoryQuantity).reduce(Long::sum).get();
        log.info("计算调拨商品总数:{}",sum);
        OutboundRecords outboundRecords = BeanUtil.copyProperties(outboundRecordsDto, OutboundRecords.class);
        outboundRecords.setRecordsCode(code);
        outboundRecords.setEnterpriseId(user.getEnterpriseId());
        outboundRecords.setEnterpriseName(user.getUserName());
        outboundRecords.setStationId(user.getStationId());
        outboundRecords.setStationName(user.getStationName());
        outboundRecords.setOutboundStationId(outboundStation.getStationId());
        outboundRecords.setOutboundStationName(outboundStation.getStationName());
        outboundRecords.setStorageStationId(storageStation.getStationId());
        outboundRecords.setStorageStationName(storageStation.getStationName());
        outboundRecords.setStatus(StorageStatusEnum.WAIT_STORAGE.getCode());
        outboundRecords.setCreateUser(user.getUserId());
        outboundRecords.setCreateUserName(user.getUserName());
        outboundRecords.setCreateTime(new Date());
        outboundRecords.setCommodityNum(sum);
        //存储出库记录
        save(outboundRecords);
        List<OutboundRecordsDetails> outboundRecordsDetailsList = new LinkedList<>();
        List<Commodity> commodityList = new LinkedList<>();
        for (OutboundRecordsDetailsDto outboundRecordsDetailsDto : outboundRecordsDetailsDtos) {
            if(outboundRecordsDetailsDto.getInventoryQuantity().compareTo(outboundRecordsDetailsDto.getInventory())>0){
                throw new BaseException("调拨数量不能大于可用库存");
            }
            long inventory = outboundRecordsDetailsDto.getInventory() - outboundRecordsDetailsDto.getInventoryQuantity();
            OutboundRecordsDetails outboundRecordsDetails = BeanUtil.copyProperties(outboundRecordsDetailsDto, OutboundRecordsDetails.class);
            outboundRecordsDetails.setOutboundRecordsId(outboundRecords.getOutboundRecordsId());
            outboundRecordsDetails.setInventory(inventory);
            outboundRecordsDetails.setCreateUser(user.getCreateName());
            outboundRecordsDetails.setCreateTime(new Date());
            //调拨出库对应减库存
            Commodity commodity = new Commodity();
            commodity.setCommodityId(outboundRecordsDetailsDto.getCommodityId());
            commodity.setInventory(inventory);
            commodityList.add(commodity);
            outboundRecordsDetailsList.add(outboundRecordsDetails);
        }
        //存储商品出库明细
        outboundRecordsDetailsService.saveBatch(outboundRecordsDetailsList);
        //调拨出库对应减库存
        commodityService.updateBatchById(commodityList);
        //同时生成入库记录
        StorageRecords storageRecords = BeanUtil.copyProperties(outboundRecordsDto, StorageRecords.class);
        storageRecords.setRecordsCode(code);
        storageRecords.setEnterpriseId(user.getEnterpriseId());
        storageRecords.setEnterpriseName(user.getUserName());
        storageRecords.setStationId(user.getStationId());
        storageRecords.setStationName(user.getStationName());
        storageRecords.setOutboundStationId(outboundStation.getStationId());
        storageRecords.setOutboundStationName(outboundStation.getStationName());
        storageRecords.setStorageStationId(storageStation.getStationId());
        storageRecords.setStorageStationName(storageStation.getStationName());
        storageRecords.setStatus(StorageStatusEnum.WAIT_STORAGE.getCode());
        storageRecords.setCreateUser(user.getUserId());
        storageRecords.setCreateUserName(user.getUserName());
        storageRecords.setCreateTime(new Date());
        storageRecords.setCommodityNum(sum);
        storageRecordsService.save(storageRecords);
        //存储商品入库明细
        List<StorageRecordsDetails> storageRecordsDetailsList = new LinkedList<>();
        for (OutboundRecordsDetailsDto outboundRecordsDetailsDto : outboundRecordsDetailsDtos) {
            if(outboundRecordsDetailsDto.getInventoryQuantity().compareTo(outboundRecordsDetailsDto.getInventory())>0){
                throw new BaseException("调拨数量不能大于可用库存");
            }
            StorageRecordsDetails storageRecordsDetails = BeanUtil.copyProperties(outboundRecordsDetailsDto, StorageRecordsDetails.class,"inventoryOutQuantity");
            storageRecordsDetails.setInventoryOutQuantity(outboundRecordsDetailsDto.getInventoryQuantity());
            storageRecordsDetails.setStorageRecordsId(storageRecords.getStorageRecordsId());
            storageRecordsDetails.setCreateUser(user.getCreateName());
            storageRecordsDetails.setCreateTime(new Date());
            storageRecordsDetailsList.add(storageRecordsDetails);
        }
        storageRecordsDetailsService.saveBatch(storageRecordsDetailsList);
        return AjaxResult.success();
    }

    @Override
    public OutboundRecordsVo selectOutboundOrderDetail(Long outboundRecordsId) {
        log.info("调拨出库详情入参：{}", outboundRecordsId);
        OutboundRecords outboundRecords = getById(outboundRecordsId);
        OutboundRecordsVo outboundRecordsVo = BeanUtil.copyProperties(outboundRecords, OutboundRecordsVo.class);
        Station outboundStation = stationMapper.selectStationById(outboundRecordsVo.getOutboundStationId());
        Station storageStation = stationMapper.selectStationById(outboundRecordsVo.getStorageStationId());
        outboundRecordsVo.setOutboundStationName(outboundStation.getStationName());
        outboundRecordsVo.setStorageStationName(storageStation.getStationName());

        LambdaQueryWrapper<OutboundRecordsDetails> wrapper = new LambdaQueryWrapper();
        wrapper.eq(OutboundRecordsDetails::getOutboundRecordsId,outboundRecords.getOutboundRecordsId());
        List<OutboundRecordsDetails> list = outboundRecordsDetailsService.list(wrapper);
        if(CollectionUtil.isNotEmpty(list)){
            List<OutboundRecordsDetailsDto> outboundRecordsDetailsDtos = BeanUtil.copyToList(list, OutboundRecordsDetailsDto.class);
            outboundRecordsVo.setOutboundRecordsDetailsDtos(outboundRecordsDetailsDtos);
        }
        return outboundRecordsVo;
    }

    @Override
    public PageInfo<OutboundRecordsVo> selectOutboundList(OutboundRecordsQueryDto outboundRecordsQueryDto) {
        log.info("出库列表入参：{}", JSONObject.toJSONString(outboundRecordsQueryDto));
        SysUser user = SecurityUtils.getLoginUser().getUser();
        if(null==user){
            throw new BaseException("当前用户不存在");
        }
        if(UserConstants.LEVEL_TWO.equals(user.getUserLevel())){
            outboundRecordsQueryDto.setEnterpriseId(user.getEnterpriseId());
        }else if(UserConstants.LEVEL_THREE.equals(user.getUserLevel())){
            outboundRecordsQueryDto.setStationId(user.getStationId());
        }
        PageHelper.startPage(outboundRecordsQueryDto.getPageNum(),outboundRecordsQueryDto.getPageSize());
        List<OutboundRecordsVo> outboundRecordsVos = baseMapper.selectOutboundList(outboundRecordsQueryDto);
        PageInfo<OutboundRecordsVo> pageInfo = new PageInfo<>(outboundRecordsVos);
        if(CollectionUtil.isNotEmpty(outboundRecordsVos)){
            outboundRecordsVos.forEach(x->{
                x.setStatusDesc(StorageStatusEnum.getMsg(x.getStatus()));
            });
            pageInfo.setList(outboundRecordsVos);
        }else{
            pageInfo.setList(new ArrayList<>());
        }
        return pageInfo;
    }
}
